/*
 * Copyright (C) 2011-2018 ShenZhen iBOXSaaS Information Technology Co.,Ltd.
 * 
 * All right reserved.
 * 
 * This software is the confidential and proprietary information of iBOXSaaS Company of China.
 * ("Confidential Information"). You shall not disclose such Confidential Information and shall use it only in
 * accordance with the terms of the contract agreement you entered into with iBOXSaaS inc.
 * 
 */

package com.iboxpay.open.auth.center.aspect;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.iboxpay.open.common.constants.LogEnums;
import org.iboxpay.open.common.utils.AccessLogUtils;
import org.iboxpay.open.common.utils.SnowflakeIdWorker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.iboxpay.common.json.MapperUtils;

/**
 * 
 * AccessLogRecordAspect.java
 * 
 * @author xuxiao
 * @date 2018/06/15
 */
@Aspect
@Component
public class AccessLogRecordAspect {

    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;

    private static final Logger interfaceLog = LoggerFactory.getLogger(LogEnums.interfaceLog.getCode());
    private static final Logger accessLogger = LoggerFactory.getLogger(LogEnums.accessLog.getCode());

    /**
     * 打印日志
     * 
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around("execution(* com.iboxpay.open.auth.center.controller.*.*(..))")
    public Object handleApi(ProceedingJoinPoint pjp) throws Throwable {
        Object result = null;
        long startTime = 0;
        long endTime = 0;
        // 生成transactionId
        String serviceId = getServiceId(pjp);
        String transactionId = String.valueOf(snowflakeIdWorker.nextId());
        MDC.put(LogEnums.serviceId.getCode(), serviceId);
        MDC.put(LogEnums.transactionId.getCode(), transactionId);
        // 执行具体方法
        interfaceLog.info("[{}] [HTTP] [request] - {}", serviceId, MapperUtils.toJson(pjp.getArgs()));
        startTime = System.currentTimeMillis();
        MDC.put(LogEnums.startTime.getCode(), String.valueOf(startTime));
        result = pjp.proceed();
        endTime = System.currentTimeMillis();
        interfaceLog.info("[{}] [HTTP] [response] - {}", serviceId, MapperUtils.toJson(result));
        HttpServletRequest request =
            ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        accessLogger.info(MapperUtils.toJson(AccessLogUtils.getAccessMap(startTime, endTime, serviceId, transactionId, LogEnums.openAuth.getCode(), result, request)));
        return result;
    }

    private String getServiceId(ProceedingJoinPoint pjp) throws Exception {
        Object target = pjp.getTarget();
        MethodSignature msig = (MethodSignature)pjp.getSignature();
        Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());

        String targetName = target.getClass().getSimpleName();
        String methodName = currentMethod.getName();
        String serviceId = String.format("%s.%s", StringUtils.defaultIfEmpty(targetName, StringUtils.EMPTY),
            StringUtils.defaultIfEmpty(methodName, StringUtils.EMPTY));

        return serviceId;
    }

}
